//
//  String+Ex.swift
//  GhostWorld
//
//  Created by Kam on 2018/4/3.
//  Copyright © 2018 LKGood. All rights reserved.
//

import Foundation

extension String {
  
  var isEmpty: Bool {
    get {
      return self.trim().count <= 0
    }
  }
  
  func trim() -> String {
    let trimedString = self.trimmingCharacters(in: .whitespacesAndNewlines)
    return trimedString
  }
  
  func removeAllWhitespaces() -> String {
    return components(separatedBy: .whitespaces).joined()
  }
  
  func isValidEmail() -> Bool {
    guard self.trim().count > 0 else {
      return false
    }
    
    let regex = "[A-Z0-9a-z._%+-]+@[A-Za-z0-9.-]+\\.[A-Za-z]{2,}"
    let predicate = NSPredicate(format: "SELF MATCHES %@", regex)
    return predicate.evaluate(with: self)
  }
  
  func isValidChineseIDNumber() -> Bool {
    guard self.trim().count > 0 else {
      return false
    }
    
    let regex = "^(\\d{14}|\\d{17})(\\d|[xX])$"
    let predicate = NSPredicate(format: "SELF MATCHES %@", regex)
    return predicate.evaluate(with: self)
  }
  
  func isValidChineseCellPhoneNumber() -> Bool {
    guard self.trim().count > 0 else {
      return false
    }
    
    let regex = "^1[3|4|5|7|8|9][0-9]{9}"
    let predicate = NSPredicate(format: "SELF MATCHES %@", regex)
    return predicate.evaluate(with: self)
  }
  
  private func md5Data() -> Data {
    let messageData = self.data(using:.utf8)!
    var digestData = Data(count: Int(CC_MD5_DIGEST_LENGTH))
    
    _ = digestData.withUnsafeMutableBytes {digestBytes in
      messageData.withUnsafeBytes {messageBytes in
        CC_MD5(messageBytes, CC_LONG(messageData.count), digestBytes)
      }
    }
    return digestData
  }
  
  func md5HexString() -> String {
    let md5Hex = md5Data().map { String(format: "%02hhx", $0) }.joined()
    return md5Hex
  }
  
  func md5Base64String() -> String {
    let md5Base64 = md5Data().base64EncodedString()
    return md5Base64
  }
  
  // sub string
  private func index(from: Int) -> Index {
    return self.index(startIndex, offsetBy: from)
  }
  
  func substring(from: Int) -> String {
    let fromIndex = index(from: from)
    return String(self[fromIndex...])
  }
  
  func substring(to: Int) -> String {
    let toIndex = index(from: to)
    return String(self[..<toIndex])
  }
  
  func substring(with r: Range<Int>) -> String {
    let startIndex = index(from: r.lowerBound)
    let endIndex = index(from: r.upperBound)
    return String(self[startIndex..<endIndex])
  }
  
  func index(of char: Character) -> Int? {
    return index(of: char).map { self.distance(from: startIndex, to: $0) }
  }
  
  /// Create `Data` from hexadecimal string representation
  ///
  /// This takes a hexadecimal representation and creates a `Data` object. Note, if the string has any spaces or non-hex characters (e.g. starts with '<' and with a '>'), those are ignored and only hex characters are processed.
  ///
  /// - returns: Data represented by this hexadecimal string.
  
  func hexadecimal() -> Data? {
    var data = Data(capacity: count / 2)
    
    let regex = try! NSRegularExpression(pattern: "[0-9a-f]{1,2}", options: .caseInsensitive)
    regex.enumerateMatches(in: self, range: NSMakeRange(0, utf16.count)) { match, flags, stop in
      let byteString = (self as NSString).substring(with: match!.range)
      var num = UInt8(byteString, radix: 16)!
      data.append(&num, count: 1)
    }
    
    guard data.count > 0 else { return nil }
    
    return data
  }
  
  func jsonDictionary() -> [String: String]? {
    if let data = self.data(using: .utf8) {
      do {
        return try JSONSerialization.jsonObject(with: data, options: []) as? [String: String]
      } catch {
        loggingPrint(error.localizedDescription)
      }
    }
    return nil
  }
  
    static func formatTimeInterval(_ interval: Int) -> String {
  
      let hours: Int = interval / 3600;
      let minutes: Int = (interval % 3600) / 60;
      let seconds: Int = (interval % 3600) % 60;
      var lengthString = "";
      if hours > 0 {
        if hours < 10 {
          lengthString.append("0\(hours):")
        } else {
          lengthString.append("\(hours):")
        }
      } else {
//        lengthString.append("00:")
      }
      if minutes > 0 {
        if minutes < 10 {
          lengthString.append("0\(minutes):")
        } else {
          lengthString.append("\(minutes):")
        }
      } else {
        lengthString.append("00:")
      }
      if seconds < 10 {
        lengthString.append("0\(seconds)")
      } else {
        lengthString.append("\(seconds)")
      }
  
      return lengthString;
    }
}
